package me.zhengjie.tool;

import com.google.common.collect.Lists;
import me.zhengjie.vo.Constant;
import me.zhengjie.vo.DateObject;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.YEARS;

/**
 * 时间日期工具类
 *
 * @author huangyh@yinhai.com
 */
public class DateUtil implements Serializable {
    private static final long serialVersionUID = -8470196314298724214L;

    public static final int[] daysInMonth = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//    public static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
//    public static final SimpleDateFormat yyyyMM = new SimpleDateFormat("yyyyMM");

    /**
     * 默认构造函数
     */
    private DateUtil() {
    }

    /**
     * 获取当前时间，格式自定义
     *
     * @param format
     * @return
     */
    public static String getCurrentTime(String format) {
        if("YYYY".equals(format.substring(0,4))){
            format = format.replace("YYYY","yyyy");
        }
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat f = new SimpleDateFormat(format);
        String returnStr = f.format(calendar.getTime());
        return returnStr;
    }

    public static Long getCurrentTime2Long() {
        String strTime = getCurrentTime("yyyyMMddHHmmss");
        return new Long(strTime);
    }

    /**
     * 获取当前时间，格式为“yyyy-MM-dd”
     *
     * @return
     */
    public static Date getCurDate() {
        String s = getCurrentTime(Constant.DEFAULT_FORMAT_YMD);
        return java.sql.Date.valueOf(s);
    }

    /**
     * 获取当前时间，格式为“yyyy-MM-dd HH:mm:ss”
     *
     * @return
     */
    public static Date getCurrentTime() {
        return DateUtils.getCurrentDate();
    }

    /**
     * 获取当前时间，格式为“yyyy-MM-dd HH:mm:ss”
     *
     * @return
     */
    public static String getCurDateTime() {
        return getCurrentTime(Constant.DEFAULT_FORMAT);
    }

    /**
     * 获取当前时间，格式为“yyyyMMddHHmmss”
     *
     * @return
     */
    public static String getStringCurDateTime() {
        return getCurrentTime(Constant.DEFAULT_FORMAT_S);
    }

    /**
     * 获取当前时间，格式为“yyyyMMdd”
     *
     * @return
     */
    public static String getStringCurDate() {
        return getCurrentTime(Constant.DEFAULT_FORMAT_DB);
    }


    /**
     * 将月数转换成年数
     *
     * @param month
     * @return
     */
    public static double monthToYear(int month) {
        return month / 12D;
    }

    /**
     * 两时间关系判断构件
     * 时间相等返回0，time1大于time2返回1，time1小于time2返回-1
     *
     * @param time1
     * @param time2
     * @return
     */
    public static int checkTime(Date time1, Date time2) {
        return time1.compareTo(time2);
    }

    /**
     * 字符串转换成日期 如果转换格式为空，则利用默认格式进行转换操作
     *
     * @param str    字符串
     * @param format 日期格式
     * @return 日期
     * @throws ParseException
     */
    public static Date str2Date(String str, String format) {
        if (null == str || "".equals(str)) {
            return null;
        }
        // 如果没有指定字符串转换的格式，则用默认格式进行转换
        if (null == format || "".equals(format)) {
            format = Constant.DEFAULT_FORMAT;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date;
        try {
            date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 字符串转换成"yyyy-MM-dd HH:mm:ss"日期
     *
     * @param str 字符串
     * @return 日期
     * @throws ParseException
     */
    public static Date str2DefaultDate(String str) {
        String format = Constant.DEFAULT_FORMAT;
        return str2Date(str, format);
    }

    /**
     * 字符串转换成"yyyy-MM-dd"日期
     *
     * @param str 字符串
     * @return 日期
     * @throws ParseException
     */
    public static Date str2YmdDate(String str) {
        String format = Constant.DEFAULT_FORMAT_YMD;
        return str2Date(str, format);
    }

    /**
     * 字符串转换成"yyyyMMdd"日期
     *
     * @param str 字符串
     * @return 日期
     * @throws ParseException
     */
    public static Date str2DbDate(String str) {
        String format = Constant.DEFAULT_FORMAT_DB;
        return str2Date(str, format);
    }

    /**
     * 字符串转换成"yyyyMM"日期
     *
     * @param str 字符串
     * @return 日期
     * @throws ParseException
     */
    public static Date str2YmDate(String str) {
        String format = Constant.DEFAULT_FORMAT_YM;
        return str2Date(str, format);
    }

    /**
     * 日期转换为字符串
     *
     * @param date   日期
     * @param format 日期格式
     * @return 字符串
     */
    public static String date2Str(Date date, String format) {
        if (null == date) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 日期转换为"yyyy-MM-dd HH:mm:ss"字符串
     *
     * @param date 日期
     * @return 字符串
     */
    public static String date2DefaultStr(Date date) {
        return date2Str(date, Constant.DEFAULT_FORMAT);
    }

    /**
     * 日期转换为"yyyy-MM-dd"字符串
     *
     * @param date 日期
     * @return 字符串
     */
    public static String date2YmdStr(Date date) {
        return date2Str(date, Constant.DEFAULT_FORMAT_YMD);
    }

    /**
     * 日期转换为"yyyyMMdd"字符串
     *
     * @param date 日期
     * @return 字符串
     */
    public static String date2DbStr(Date date) {
        return date2Str(date, Constant.DEFAULT_FORMAT_DB);
    }

    /**
     * 日期转换为"yyyyMM字符串
     *
     * @param date 日期
     * @return 字符串
     */
    public static String date2YmStr(Date date) {
        return date2Str(date, Constant.DEFAULT_FORMAT_YM);
    }


    /**
     * 时间戳转换为字符串
     *
     * @param time
     * @return
     */
    public static String timestamp2Str(Timestamp time) {
        Date date = null;
        if (null != time) {
            date = new Date(time.getTime());
        }
        return date2Str(date, Constant.DEFAULT_FORMAT);
    }

    /**
     * 字符串转换时间戳
     *
     * @param str
     * @return
     */
    public static Timestamp str2Timestamp(String str) {
        NPETool.isEmptyThrowException(str, "传入时间");
        Long time = str2Date(str, Constant.DEFAULT_FORMAT).getTime();
        if (ValidateUtil.isEmpty(time)) {
            throw new IllegalArgumentException("时间转换异常");
        } else {
            Timestamp timestamp = new Timestamp(time);
            return timestamp;
        }
    }

    /**
     * 字符串转换时间戳
     *
     * @param str
     * @param format
     * @return
     */
    public static Timestamp str2Timestamp(String str, String format) {
        NPETool.isEmptyThrowException(str, "传入时间");
        NPETool.isEmptyThrowException(format, "时间格式");
        Date date = str2Date(str, format);
        if (null != date) {
            return new Timestamp(date.getTime());
        }
        return null;
    }

    /**
     * 打印日期字符格式（yyyy-MM-dd hh:mm:ss）
     *
     * @param longValue
     * @return
     */
    public static String long2Str(Long longValue) {
        SimpleDateFormat format = new SimpleDateFormat(Constant.DEFAULT_FORMAT);
        return format.format(parseDate(longValue));
    }

    /**
     * 秒转化为天小时分秒字符串
     *
     * @param seconds
     * @return String
     */
    public static String formatSeconds(long seconds) {
        String timeStr = seconds + "秒";
        if (seconds > 60) {
            long second = seconds % 60;
            long min = seconds / 60;
            timeStr = min + "分" + second + "秒";
            if (min > 60) {
                min = (seconds / 60) % 60;
                long hour = (seconds / 60) / 60;
                timeStr = hour + "小时" + min + "分" + second + "秒";
                if (hour > 24) {
                    hour = ((seconds / 60) / 60) % 24;
                    long day = (((seconds / 60) / 60) / 24);
                    timeStr = day + "天" + hour + "小时" + min + "分" + second + "秒";
                }
            }
        }
        return timeStr;
    }

    public static Timestamp long2Timestamp(Long longValue) {
        return new Timestamp(longValue);
    }

    /**
     * long解析为java.util.Date
     *
     * @param longValue
     * @return
     */
    public static Date parseDate(long longValue) {
        return new Date(longValue);
    }

    /**
     * 判断两个java.util.Date是否为同一天（相同的天号）
     * 2019-01-01和2020-02-01 都是1号，返回true
     * 2019-01-01和2020-02-02 不是一天，返回false
     *
     * @param date1
     * @param date2
     * @return
     */
    @SuppressWarnings("deprecation")
    public static boolean isSameDay(Date date1, Date date2) {
        return date1.getDate() == date2.getDate();
    }

    /**
     * 获取两个日期之间的月数
     *
     * @param start
     * @param end
     * @return
     */
    public static int getMonths(Date start, Date end) {
        SimpleDateFormat sdf = new SimpleDateFormat(Constant.DEFAULT_FORMAT_YM);
        Integer start_s = Integer.parseInt(sdf.format(start));
        Integer end_s = Integer.parseInt(sdf.format(end));
        return Ym.monthsBetween(start_s, end_s);

    }

    /**
     * 计算两个long（秒）之间相差的天数
     *
     * @param longValue1
     * @param longValue2
     * @return
     */
    public static int getBetweenDays(long longValue1, long longValue2) {
        long betweenDays = ((longValue1 - longValue2) / 1000) / (60 * 60 * 24);
        return Math.abs((int) betweenDays);
    }

    /**
     * @param time1
     * @param time2
     * @return
     * @Description: 计算2个日期Str的天数
     * @update: 2014-1-8 by huangyh
     */
    public static int getBetweenDays(String time1, String time2) {
        long betweenDays = 0;
        SimpleDateFormat ft = new SimpleDateFormat(Constant.DEFAULT_FORMAT_DB);
        try {
            Date date1 = ft.parse(time1);
            Date date2 = ft.parse(time2);
            betweenDays = date1.getTime() - date2.getTime();
            betweenDays = betweenDays / 1000 / 60 / 60 / 24;
        } catch (ParseException e) {
            LogUtil.error(e);
        }
        return Math.abs((int) betweenDays);
    }

    /**
     * 计算两个日期之间相差多少天
     *
     * @param time1
     * @param time2
     * @return
     */
    public static int getBetweenDays(Date time1, Date time2) {
        Date temp;
        if (time1.after(time2)) { //日期one大于日期second
            temp = time1;
            time1 = time2;
            time2 = temp;
        }

        Calendar calOne = Calendar.getInstance();
        calOne.setTime(time1);

        Calendar calSecond = Calendar.getInstance();
        calSecond.setTime(time2);

        int dayOne = calOne.get(Calendar.DAY_OF_YEAR);
        int daySecond = calSecond.get(Calendar.DAY_OF_YEAR);

        int yearOne = calOne.get(Calendar.YEAR);
        int yearSecond = calSecond.get(Calendar.YEAR);

        if (yearOne != yearSecond) { //不同年
            int timeDistance = 0;
            for (int i = yearOne; i < yearSecond; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {    //闰年
                    timeDistance += 366;

                } else {    //不是闰年
                    timeDistance += 365;

                }
            }

            return timeDistance + (daySecond - dayOne);
        } else {    //不同年

            return daySecond - dayOne;
        }

    }

    /**
     * sql.Date转化为sql.Timestamp
     *
     * @param date
     * @return
     */
    public static Timestamp convertDate2Timestamp(Date date) {
        return new Timestamp(date.getTime());
    }

    /**
     * @param date
     * @param days
     * @return
     * @Description: 获取下一天
     * @update: 2016年1月5日 by huangyh
     */
    @SuppressWarnings("static-access")
    public static Timestamp getNextDay(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(calendar.DATE, days);// 把日期往后增加一天.整数往后推,负数往前移动
        return convertDate2Timestamp(calendar.getTime());
    }

    /**
     * @param date1
     * @param date2
     * @param format
     * @return
     * @Description: 比较两个日期的大小
     * @update: 2014年8月4日 by huangyh
     */
    public static int compareDate(String date1, String date2, String format) {
        // if (ObjectUtil.isEmpty(format)) {
        // format = DEFAULT_FORMAT;
        // }
        DateFormat df = new SimpleDateFormat(format);
        try {
            Date dt1 = df.parse(date1);
            Date dt2 = df.parse(date2);
            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        } catch (Exception exception) {
            LogUtil.error(exception);
        }
        return 0;
    }


    /**
     * 将数字转为日期格式（主要用于处理数据库中日期为NUMBER的查询）
     *
     * @param value
     * @param format
     * @return
     */
    public static Date integer2Date(Integer value, String format) {
        if (value == null) {
            return null;
        }
        String str = String.valueOf(value);
        if (format == null || "".equals(format)) {
            format = Constant.DEFAULT_FORMAT_DB;
        }
        return str2Date(str, format);
    }

    /**
     * 时间转换为integer
     *
     * @param date
     * @param format
     * @return
     */
    public static Integer date2Integer(Date date, String format) {
        String str = date2Str(date, format);
        Integer value = Integer.valueOf(str);
        return value;
    }

    /**
     * 字符串转换为integer
     * string-date-integer
     *
     * @param date
     * @param format
     * @return
     */
    public static Integer string2Integer(String date, String format) {
        if (ValidateUtil.isEmpty(date)) {
            return null;
        }
        Date temp = str2Date(date, format);
        if (ValidateUtil.isEmpty(temp)) {
            return null;
        }
        return date2Integer(temp, format);
    }

    /**
     * Date增减day
     *
     * @param date 基础日期
     * @param day  增减天数
     * @return
     * @
     */
    public static Date addDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }

    /**
     * Date增减month
     *
     * @param date  基础日期
     * @param month 增减月数
     * @return
     * @
     */
    public static Date addMonth(Date date, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        return calendar.getTime();
    }

    /**
     * Date增减month
     *
     * @param aae003(yyyyMM)
     * @param month          增减月数
     * @return
     * @
     */
    public static Integer addMonth(Integer aae003, int month) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat(Constant.DEFAULT_FORMAT_YM);
        Date date = format.parse(aae003.toString());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        Integer outIntrger = Integer.valueOf(format.format(calendar.getTime()));
        return outIntrger;
    }


    /**
     * Date增减year
     *
     * @param date 基础日期
     * @param year 增减年数
     * @return
     * @
     */
    public static Date addYear(Date date, int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, year);
        return calendar.getTime();
    }

    /**
     * 获取前台展示时间yyyy-MM-dd
     *
     * @param o
     * @return
     */
    public static String getShowDate(Object o) {
        if (!ValidateUtil.isEmpty(o)) {
            if (o instanceof BigDecimal) {
                BigDecimal big = (BigDecimal) o;
                return getShowDate(big.toString());
            }
            if (o instanceof Integer) {
                Integer integer = (Integer) o;
                return getShowDate(integer.toString());
            }
            if (o instanceof Date) {
                Date date = (Date) o;
                return date2Str(date, Constant.DEFAULT_FORMAT_YMD);
            }
            if (o instanceof String) {
                String s = (String) o;
                return getShowDate(s);
            }
        }
        return null;
    }

    /**
     * 获取显示时间
     *
     * @param s
     * @return
     */
    private static String getShowDate(String s) {
        if (ValidateUtil.isNotEmpty(s) && s.length() == 8) {
            s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-" + s.substring(6, 8);
            return s;
        }
        if (ValidateUtil.isNotEmpty(s) && s.length() == 6) {
            s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-01";
            return s;
        }
        return s;
    }

    /**
     * 获取某个月的最后一天
     *
     * @param year  年
     * @param month 月
     * @return
     */
    public static String getLastDayOfMonth(int year, int month, String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, maxDay);
        return date2Str(calendar.getTime(), format);
    }

    /***
     *〈获取当前月第一天〉
     * @return
     * @see  [类、类#方法、类#成员]
     */
    public static String getMonthOfDayFirst() {
        SimpleDateFormat format = new SimpleDateFormat(Constant.DEFAULT_FORMAT_YMD);
        String firstDay = "";
        // 获取前月的第一天
        Calendar cal_1 = Calendar.getInstance();
        cal_1.add(Calendar.MONTH, 0);
        cal_1.set(Calendar.DAY_OF_MONTH, 1);
        firstDay = format.format(cal_1.getTime());

        return firstDay;
    }

    /***
     *〈获取当前日期〉
     * @return
     * @see  [类、类#方法、类#成员]
     */
    public static String getMonthToday() {
        SimpleDateFormat format = new SimpleDateFormat(Constant.DEFAULT_FORMAT_YMD);
        String firstDay = "";
        // 获取前月的第一天
        Calendar cal = Calendar.getInstance();
        firstDay = format.format(cal.getTime());

        return firstDay;
    }

    /**
     * 判断两个时间段是否有重叠部分
     *
     * @param startdate1
     * @param enddate1
     * @param startdate2
     * @param enddate2
     * @param format
     * @return
     */
    public static boolean isHaveOverlap(String startdate1, String enddate1,
                                        String startdate2, String enddate2, String format) {

        boolean isHave = false;
        DateFormat df = new SimpleDateFormat(format);

        try {
            Date compareStartDate1 = df.parse(startdate1);
            Date compareEndDate1 = df.parse(enddate1);
            Date compareStartDate2 = df.parse(startdate2);
            Date compareEndDate2 = df.parse(enddate2);

            if (compareStartDate1.getTime() <= compareEndDate2.getTime() &&
                    compareEndDate1.getTime() >= compareStartDate2.getTime()) {
                isHave = true;
            }

        } catch (ParseException e) {
            LogUtil.error(e);
        }

        return isHave;
    }

    /**
     * 获取上年末
     *
     * @return
     */
    public static Integer getLastYearMonths() {
        return Integer.valueOf(DateUtil.getYear(DateUtil.getCurDate()) - 1 + "12");
    }

    private boolean isNonnegativeInteger(String s) {
        if (ValidateUtil.isEmpty(s)) {
            return true;
        }
        try {
            int temp = Integer.parseInt(s);

            return temp >= 0;
        } catch (Exception e) {
            return false;
        }
    }

    private boolean isYear(String s) {
        if (ValidateUtil.isEmpty(s)) {
            return true;
        }

        if (!isNonnegativeInteger(s)) {
            return false;
        }
        return (s.length() == 2) || (s.length() == 4);
    }

    private boolean isSignedInteger(String s) {
        if (ValidateUtil.isEmpty(s)) {
            return true;
        }
        try {
            Integer.parseInt(s);
            return true;
        } catch (Exception e) {
            return false;
        }

    }

    private boolean isIntegerInRange(String s, int a, int b) {
        if (ValidateUtil.isEmpty(s)) {
            return true;
        }

        if (!isSignedInteger(s)) {
            return false;
        }

        int num = Integer.parseInt(s);

        return (num >= a) && (num <= b);
    }

    private boolean isMonth(String s) {
        if (ValidateUtil.isEmpty(s)) {
            return true;
        }
        return isIntegerInRange(s, 1, 12);
    }

    private boolean isDay(String s) {
        if (ValidateUtil.isEmpty(s)) {
            return true;
        }
        return isIntegerInRange(s, 1, 31);
    }

    private int daysInFebruary(int year) {
        return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) ? 29 : 28;
    }

    private boolean isDate(String year, String month, String day) {
        if ((!isYear(year)) || (!isMonth(month)) || (!isDay(day))) {
            return false;
        }

        int intYear = Integer.parseInt(year);
        int intMonth = Integer.parseInt(month);
        int intDay = Integer.parseInt(day);

        if (intDay > daysInMonth[(intMonth - 1)]) {
            return false;
        }
        return (intMonth != 2) || (intDay <= daysInFebruary(intYear));
    }

    public static boolean isDate(String date) {
        if (ValidateUtil.isEmpty(date)) {
            return true;
        }

        int dateSlash1 = date.indexOf('-');
        int dateSlash2 = date.lastIndexOf('-');

        if ((dateSlash1 <= 0) || (dateSlash1 == dateSlash2)) {
            return false;
        }
        String year = date.substring(0, dateSlash1);
        String month = date.substring(dateSlash1 + 1, dateSlash2);
        String day = date.substring(dateSlash2 + 1);

        return new DateUtil().isDate(year, month, day);
    }

    /**
     * 期号增减
     *
     * @param issue
     * @return
     */
    public static int issueRegulation(Integer issue, Integer counter) {
        Integer year = issue / 100;
        Integer months = issue % 100;
        if (counter / 12 != 0) {
            year += counter / 12;
        }
        if (months + counter % 12 > 12) {
            year += 1;
            months = months + counter % 12 - 12;
        } else if (months + counter % 12 <= 0) {
            year -= 1;
            months = months + counter % 12 + 12;
        } else {
            months += counter % 12;
        }
        return year * 100 + months;
    }


    /**
     * 匹配期号-aae003与myMap中aae041,aae042比较
     *
     * @param myMap
     * @param aae003
     * @return
     */
    public static boolean equalsDate(MyMap myMap, Integer aae003) {
        if (ValidateUtil.isEmpty(myMap.get("aae041"))) {
            return false;
        }
        if (myMap.getAsInteger("aae041").intValue() <= aae003.intValue()
                && (aae003.intValue() <= (ValidateUtil.isEmpty(myMap.get("aae042")) ? 999912 : myMap.getAsInteger("aae042")))) {
            return true;
        }
        return false;
    }

    /**
     * @param date
     * @return java.lang.Integer
     * @Author yinyb(rtx)
     * @Descripton 获取年龄
     * @Date 11:52 2019/11/8
     */
    public static long getAge(Date date) {
        LocalDateTime beginYear = dateToLocalDateTime(date);
        LocalDateTime endYear = LocalDateTime.now();
        long until = beginYear.until(endYear, YEARS);
        return until;
    }
    /** @return 周岁*/
    public static int getAge(String birth,String current)  {
        Assert.hasLength(birth, "出生日期违法");
        Assert.hasLength(current, "当前日期违法");

        if (birth.length()!= 8){
            throw new IllegalArgumentException("出生日期应该为8位");
        }
        if (current.length()!= 8){
            throw new IllegalArgumentException("当前日期应该为8位");
        }
        Date birthDay = null;
        Date now = null;
        try {
            birthDay = new SimpleDateFormat("yyyyMMdd").parse(birth);
            now = new SimpleDateFormat("yyyyMMdd").parse(current);
        } catch (ParseException e) {
            LogUtil.error(e);
            return -1;
        }
        int age = now.getYear() - birthDay.getYear()-1;
        if (now.getMonth() > birthDay.getMonth()){
            age++;
        }else if(now.getDate() >= birthDay.getDate() && now.getMonth() == birthDay.getMonth()){
            age++;
        }
        return age;
    }

    /**
     * @param date
     * @return
     * @Author yinyb(rtx)
     * @Descripton
     * @Date 11:01 2019/11/8
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        // Date转LocalDate
        // date转毫秒
        Instant instant = date.toInstant();
        // 获取系统默认时区
        ZoneId zoneId = ZoneId.systemDefault();
        // 转LocalDateTime
        return LocalDateTime.ofInstant(instant, zoneId);
    }

    /**
     * 求开放时间区间与时间区间的所有交集
     *
     * @param dateObject 日期对象
     * @param list       日期列表
     * @return 日期交集
     */
    public static List<DateObject> intersection(DateObject dateObject, List<DateObject> list) {
        List<DateObject> result = Lists.newArrayList();
        for (DateObject date : list) {
            // 时间区间全部在开放时间区间内：ad.startDate <= open.startDate < open.endDate <= ad.endDate
            // 则[open.startDate, open.endDate] 均不开放
            if (date.getStartDate().getTime() <= dateObject.getStartDate().getTime()
                    && date.getEndDate().getTime() >= dateObject.getEndDate().getTime()) {
                // 开放时间区间已全部占用
                break;
            }
            // 时间区间全部在开放时间区间内：open.startDate <= ad.startDate < ad.endDate <= open.endDate
            else if (date.getStartDate().getTime() >= dateObject.getStartDate().getTime()
                    && date.getEndDate().getTime() <= dateObject.getEndDate().getTime()) {
                result.add(new DateObject(date.getStartDate(), date.getEndDate()));
            }
            // 结束时间在开放时间区间内：ad.startDate <= open.startDate <= ad.endDate <= open.endDate
            else if (date.getStartDate().getTime() <= dateObject.getStartDate().getTime()
                    && date.getEndDate().getTime() >= dateObject.getStartDate().getTime()
                    && date.getEndDate().getTime() <= dateObject.getEndDate().getTime()) {
                result.add(new DateObject(dateObject.getStartDate(), date.getEndDate()));
            }
            // 开始时间在开放时间区间内：open.startDate <= ad.startDate <= open.endDate <= ad.endDate
            else if (date.getEndDate().getTime() > dateObject.getEndDate().getTime()) {
                result.add(new DateObject(date.getStartDate(), dateObject.getEndDate()));
            }
        }
        return result;
    }

    /**
     * 时间区间合并
     *
     * @param list 日期集合
     * @return 合并后日期集合
     */
    public static List<DateObject> merge(List<DateObject> list) {
        if (list == null || list.size() == 0) {
            return Lists.newArrayList();
        }

        List<DateObject> result = Lists.newArrayList();
        DateObject first = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            DateObject next = list.get(i);
            // 合并区间，时间精确到秒（差1秒则为连续）
            if (next.getStartDate().getTime() < first.getEndDate().getTime() || next.getStartDate().getTime() - first.getEndDate().getTime() == 1000) {
                first.setStartDate(new Date(Math.min(first.getStartDate().getTime(), next.getStartDate().getTime())));
                first.setEndDate(new Date(Math.max(first.getEndDate().getTime(), next.getEndDate().getTime())));
            } else {
                // 没有交集，直接添加
                result.add(first);
                first = next;
            }
        }
        result.add(first);
        return result;
    }

    /**
     * 求差集
     *
     * @param dateObject 日期对象
     * @param list       日期列表
     * @return 差集
     */
    public static List<DateObject> differences(DateObject dateObject, List<DateObject> list) {
        List<DateObject> result = Lists.newArrayList();
        DateObject first = list.get(0);
        if (list.size() == 1) {
            if (dateObject.getStartDate().getTime() < first.getStartDate().getTime()) {
                result.add(new DateObject(dateObject.getStartDate(), DateUtil.getEndTimeOfDay(DateUtil.plusDays(first.getStartDate(), -1))));
            }
            if (dateObject.getEndDate().getTime() - first.getEndDate().getTime() > 1000) {
                result.add(new DateObject(DateUtil.getFirstTimeOfDay(DateUtil.plusDays(first.getEndDate(), 1)), DateUtil.getEndTimeOfDay(dateObject.getEndDate())));
            }
        } else {
            for (int i = 1; i < list.size(); i++) {
                DateObject next = list.get(i);
                result.add(new DateObject(DateUtil.getFirstTimeOfDay(DateUtil.plusDays(first.getEndDate(), 1)), DateUtil.getEndTimeOfDay(DateUtil.plusDays(next.getStartDate(), -1))));
                first = next;
            }
            DateObject last = list.get(list.size() - 1);
            if (dateObject.getEndDate().getTime() > last.getEndDate().getTime()) {
                result.add(new DateObject(DateUtil.getFirstTimeOfDay(DateUtil.plusDays(last.getEndDate(), 1)), DateUtil.getEndTimeOfDay(dateObject.getEndDate())));
            }
        }
        return result;
    }

    private static Date plusDays(Date date, Integer count) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime localDateTime1 = localDateTime.plusDays(count);
        // LocalDateTime转Date
        return localDateTimeToDate(localDateTime1);
    }

    private static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    /**
     * 获取date当天的最后时间
     *
     * @param date 日期
     * @return date当天的最后时间
     */
    public static Date getEndTimeOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return Date.from(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取date当天的开始日期
     *
     * @param date 日期
     * @return date当天的开始日期
     */
    public static Date getFirstTimeOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return Date.from(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取两个期号之间的所以期号包含自己
     *
     * @param begin 开始期号
     * @param end   结束期号
     * @return
     */
    public static List<Integer> getAllIssueBetweenBeginAndEnd(Integer begin, Integer end) {
        long countMouth = getBetweenCountIssue(begin, end);
        List<Integer> issues = new ArrayList<>();
        Integer temp = begin;
        for (int i = 0; i < countMouth; i++) {
            issues.add(temp);
            temp = addIssue(temp, 1);
        }
        return issues;
    }

    /**
     * 获取两个期号之间的所以期号包含自己
     *
     * @param begin 开始期号
     * @param end   结束期号
     * @return
     */
    public static List<Integer> getAllYear(Integer begin, Integer end) {
        Integer yearStart = begin / 100;
        Integer yearEnd = end / 100;
        if (yearStart > yearEnd) {
            throw new IllegalArgumentException("开始年度的大于结束年度");
        }
        List<Integer> issues = new ArrayList<>();
//        Integer temp = begin;
        while (yearStart <= yearEnd) {
            issues.add(yearStart);
            yearStart = yearStart + 1;
        }
        return issues;
    }

    /**
     * 获取两个期号之间每年最大值和最小值以及月数
     *
     * @param begin 开始期号
     * @param end   结束期号
     * @return
     */
    public static Map getAllYearMaxAndMin(Integer begin, Integer end) {
        List<Integer> issues = getAllIssueBetweenBeginAndEnd(begin, end);
        Map<Integer, Map> result = new HashMap<>();
        issues.stream().collect(Collectors.groupingBy(integer -> integer / 100)).forEach((aae001, values) -> {
            Map map = new HashMap();
            map.put("aae041", Collections.min(values));
            map.put("aae042", Collections.max(values));
            map.put("months", values.size());
            result.put(aae001, map);
        });
        return result;
    }

    /**
     * 获取两个期号之间的月数
     *
     * @param begin 开始期号
     * @param end   结束期号
     * @return
     */
    public static long getBetweenCountIssue(Integer begin, Integer end) {
        return getBetweenCountMouth(issueToDate(begin), issueToDate(end)) + 1;
    }

    /**
     * 获取两个时间段之间的月份数
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return
     */
    public static long getBetweenCountMouth(Date begin, Date end) {
        LocalDateTime beginDate = dateToLocalDateTime(begin);
        LocalDateTime endDate = dateToLocalDateTime(end);
        return beginDate.until(endDate, MONTHS);
    }

    /**
     * 期号转日期
     *
     * @param issue 期号
     * @return
     */
    public static Date issueToDate(Integer issue) {
        // issue 转 localDate
        LocalDate localDate = issueToLocalDate(issue);
        return localDateToDate(localDate);
    }

    /**
     * issue 转 localDate
     *
     * @param issue 期号
     * @return
     */
    private static LocalDate issueToLocalDate(Integer issue) {
        StringBuffer sb = new StringBuffer(issue + "");
        sb.append("01");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        return LocalDate.parse(sb, formatter);
    }

    /**
     * localDate转Date
     *
     * @param parse 本地日期
     * @return
     */
    private static Date localDateToDate(LocalDate parse) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = parse.atStartOfDay().atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    /**
     * 期号的加减
     *
     * @param issue 期号
     * @param count 月数
     * @return
     */
    public static Integer addIssue(Integer issue, Integer count) {
        LocalDate localDate = issueToLocalDate(issue);
        DateTimeFormatter yyyyMM = DateTimeFormatter.ofPattern("yyyyMM");
        LocalDate localDate1 = localDate.plusMonths(count);
        String format = localDate1.format(yyyyMM);
        return Integer.valueOf(format);
    }

    /**
     * 获取当前时间年
     *
     * @param date
     * @return
     */
    public static Integer getYear(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        return localDateTime.getYear();
    }

    /**
     * 获取月份
     *
     * @param date
     * @return
     */
    public static String getMouth(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        int value = localDateTime.getMonth().getValue();
        if (value < 10) {
            return "0" + value;
        }
        return value + "";
    }

    /**
     * 获取给定日期的上年年月
     *
     * @param date
     * @return
     */

    public static String getLastYearMonth(Date date) {
        // 将 Date 转换为 LocalDate
        LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        // 获取去年的年份和当前月份
        int lastYear = localDate.minusYears(1).getYear();
        int month = localDate.getMonthValue();

        // 格式化为年月字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
        return formatter.format(LocalDate.of(lastYear, month, 1));
    }


    /**
     * 获取两个年度之间的所有年度 包含自己
     *
     * @param startYear
     * @param endYear
     * @return
     */
    public static List<Integer> getBetweenAllYear(Integer startYear, Integer endYear) {
        if (endYear < startYear) {
            throw new IllegalArgumentException("结束年必须大于等于开始年");
        }
        List<Integer> allYear = new ArrayList<>();
        allYear.add(startYear);
        int count = endYear - startYear;
        for (int i = 1; i <= count; i++) {
            allYear.add(startYear + i);
        }
        return allYear;
    }

    /**
     * 日期转期号
     *
     * @param date
     * @return
     */
    public static Integer toIssue(Date date) {
        return Integer.valueOf(getYear(date) + "" + getMouth(date));
    }

    /**
     * 字符串转时间
     *
     * @param date
     * @param format
     * @param containsSFM
     * @return
     */
    public static Date stringToDate(String date, String format, Boolean containsSFM) {
        // 避免时间格式化传入的SS为大写导致程序报错（SS为毫秒数，ss才是一分钟内的某一秒）
        String s = format.replaceAll("SS", "ss");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(s);
        if (containsSFM) {
            LocalDateTime parse = LocalDateTime.parse(date, formatter);
            return localDateTimeToDate(parse);
        } else {
            LocalDate parse = LocalDate.parse(date, formatter);
            return localDateToDate(parse);
        }
    }

    /**
     * yyyyMMddHHmmss的字符串转换为x年x月x日x时x分x秒
     *
     * @param date yyyyMMddHHmmss
     * @return 转换后的日期字符串
     */
    public static String ys2Chinese(String date) {

        if (ValidateUtil.isEmpty(date) || date.length() != 14) {
            return date;
        }
        String pattern = "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
        Pattern pattern1 = Pattern.compile(pattern);
        Matcher matcher = pattern1.matcher(date);
        if (matcher.find()) {
            String year = matcher.group(1);
            String month = matcher.group(2);
            String day = matcher.group(3);
            String hour = matcher.group(4);
            String minute = matcher.group(5);
            return year + "年" + month + "月" + day + "日" + hour + "时" + minute + "分";
        } else {
            return date;
        }
    }

    /**
     * 判断两个日期间的天数，排除周末
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int getDays(Date startTime, Date endTime) {
        int leaveDays = 0;
        Date flag = startTime;//设置循环开始日期
        Calendar cal = Calendar.getInstance();

        cal.setTime(flag);
        cal.add(Calendar.DAY_OF_MONTH, +1);
        flag = cal.getTime();

        while (flag.compareTo(endTime) <= 0) {
            cal.setTime(flag);
            int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
            if (week == 0 || week == 6) {//0为周日，6为周六
                cal.add(Calendar.DAY_OF_MONTH, +1);
                flag = cal.getTime();
                continue;
            }
            leaveDays = leaveDays + 1;
            cal.add(Calendar.DAY_OF_MONTH, +1);
            flag = cal.getTime();
        }
        return leaveDays;
    }

    /**
     * 校验是否是周末
     *
     * @param time
     * @return
     */
    public static boolean checkWeekend(Date time) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(time);
        int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
        return (week == 0 || week == 6);
    }

    /**
     * 校验日期格式
     *
     * @param datestr 日期
     * @param format  格式 为空默认为yyyyMMdd
     * @return
     */
    public static boolean validDateEffecitive(String datestr, String format) {
        if (ValidateUtil.isEmpty(format)) {
            format = "yyyyMMdd";
        }
        if (ValidateUtil.isEmpty(datestr)) {
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setLenient(false);
        try {
            sdf.parse(datestr);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 获取两个日期之间的所有月份 (年月)
     *
     * @param startTime
     * @param endTime
     * @return：YYYY-MM
     */
    public static List<String> getMonthBetweenDate(String startTime, String endTime){
        String y1 = "2016-02";// 开始时间
        String y2 = "2019-12";// 结束时间

        try {
            Date startDate = new SimpleDateFormat("yyyyMM").parse(startTime);
            Date endDate = new SimpleDateFormat("yyyyMM").parse(endTime);

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            // 获取开始年份和开始月份
            int startYear = calendar.get(Calendar.YEAR);
            int startMonth = calendar.get(Calendar.MONTH);
            // 获取结束年份和结束月份
            calendar.setTime(endDate);
            int endYear = calendar.get(Calendar.YEAR);
            int endMonth = calendar.get(Calendar.MONTH);
            //
            List<String> list = new ArrayList<String>();
            for (int i = startYear; i <= endYear; i++) {
                String date = "";
                if (startYear == endYear) {
                    for (int j = startMonth; j <= endMonth; j++) {
                        if (j < 9) {
                            date = i + "0" + (j + 1);
                        } else {
                            date = i + "" + (j + 1);
                        }
                        list.add(date);
                    }

                } else {
                    if (i == startYear) {
                        for (int j = startMonth; j < 12; j++) {
                            if (j < 9) {
                                date = i + "0" + (j + 1);
                            } else {
                                date = i + "" + (j + 1);
                            }
                            list.add(date);
                        }
                    } else if (i == endYear) {
                        for (int j = 0; j <= endMonth; j++) {
                            if (j < 9) {
                                date = i + "0" + (j + 1);
                            } else {
                                date = i + "" + (j + 1);
                            }
                            list.add(date);
                        }
                    } else {
                        for (int j = 0; j < 12; j++) {
                            if (j < 9) {
                                date = i + "0" + (j + 1);
                            } else {
                                date = i + "" + (j + 1);
                            }
                            list.add(date);
                        }
                    }

                }

            }

            // 所有的月份已经准备好
            return list;

        } catch (Exception e) {
            LogUtil.error(e);
        }
        return new ArrayList<>();
    }

    public static String monthAdd(String aac327,Integer months){
        String format = null;
        try {
            Date parse = new SimpleDateFormat("yyyyMM").parse(aac327.substring(0,6));
            Calendar instance = Calendar.getInstance();
            instance.setTime(parse);
            instance.add(Calendar.MONTH,months);
            format = new SimpleDateFormat("yyyyMM").format(instance.getTime());
        } catch (ParseException e) {
            LogUtil.error(e);
        }
        return format;
    }
    public static String dateAddFiled(String aac327,SimpleDateFormat format,int filed, Integer count){
        String res = null;
        try {
            Date parse = format.parse(aac327);
            Calendar instance = Calendar.getInstance();
            instance.setTime(parse);
            instance.add(filed,count);
            res = format.format(instance.getTime());
        } catch (ParseException e) {
            LogUtil.error(e);
        }
        return res;
    }
}
